#include "StdAfx.h"
#include "QvThread.h"
#include "QvSystem.h"

QvThread::QvThread(void) : m_theParam(NULL), m_hThread(NULL)
{
    m_uThreadId = 0;
    m_isCanceled = FALSE;
    m_nExitCode = 0;
    m_isThreadRunning = FALSE;
}

QvThread::~QvThread(void)
{
    if(m_hThread)
    {
        WaitForSingleObject(m_hThread, INFINITE);
    }
    End();
}

void QvThread::Start(QvData theParam, QvUInt32 nDelayTime)
{
    if(m_hThread)
    {
        throw L"Thread is running...";
    }
    m_nDelayTime = nDelayTime;
    m_theParam = theParam;
    m_isCanceled = FALSE;
    m_nExitCode = 0;
    m_isThreadRunning = FALSE;
    m_hThread = CreateThread(NULL, 0, QvThread::ThreadProc, this, 0, &m_uThreadId);
}

void QvThread::Pause()
{
    if(m_hThread)
    {
        m_isThreadRunning = FALSE;
        SuspendThread(m_hThread);
    }
}

void QvThread::Resume()
{
    if(m_hThread)
    {
        m_isThreadRunning = TRUE;
        ResumeThread(m_hThread);
    }
}

void QvThread::End()
{
    m_isCanceled = TRUE;
}

QvULong QvThread::GetThreadId()
{
    return m_uThreadId;
}

QvBoolean QvThread::IsThreadRunning()
{
    return m_isThreadRunning;
}

QvBoolean QvThread::IsThreadExit()
{
    return (m_hThread == NULL);
}

QvULong __stdcall QvThread::ThreadProc(QvData theParam)
{
    QvULong uResult = -1;
    QvThread* thread = reinterpret_cast<QvThread*>(theParam);
    if(thread)
    {
        if(thread->m_nDelayTime > 0)
        {
            ::Sleep(thread->m_nDelayTime);
        }
        thread->m_isThreadRunning = TRUE;
        uResult = thread->m_nExitCode = thread->Run(thread->m_theParam);
        ::CloseHandle(thread->m_hThread);
        thread->m_hThread = NULL;
        thread->m_isThreadRunning = FALSE;
    }
    return uResult;
}

void QvThread::Sleep(QvInt32 uMilliseconds)
{
    ::Sleep(uMilliseconds);
}

QvBoolean QvThread::TryLock()
{
    // Request ownership of the critical section.
    return QvSystem::Thread_TryLock(); 
}

void QvThread::Lock()
{
    // Request ownership of the critical section.
    QvSystem::Thread_Lock(); 
}

void QvThread::Unlock()
{
    // Release ownership of the critical section.
    QvSystem::Thread_Unlock();
}


